<template>
  <div class="jstree jstree-default" :class="[{'jstree-checkbox-selection': showCheckbox}]">
    <ul :class="nodeClasses" v-if="data && data.length">
      <tree-node
        v-for="(item, index) in data"
        :key="item"
        :data="item"
        :lastrow="data.length > 1 && (index + 1) === data.length"
        :wholerow="wholerow"
        :show-checkbox="showCheckbox"
        :multiple="multiple">
      </tree-node>
    </ul>
  </div>
</template>

<script>
  import TreeNode from './node.vue'
  import Emitter from './emitter'
  import {findComponentsDownward} from './assist'

  export default {
    name: 'Tree',
    componentName: 'Tree',
    mixins: [ Emitter ],
    components: {TreeNode},

    props: {
      data: {
        type: Array,
        default () {
          return []
        }
      },
      showCheckbox: {
        type: Boolean,
        default: false
      },
      multiple: {
        type: Boolean,
        default: false
      },
      wholerow: {
        type: Boolean,
        default: false
      },
      emptyText: {
        type: String
      }
    },
    data () {
      return {}
    },
    computed: {
      nodeClasses () {
        return [
          'jstree-container-ul',
          'jstree-children',
          {
            'jstree-wholerow-ul': this.wholerow,
            'jstree-no-dots': this.showCheckbox

          }
        ]
      }
    },
    mounted () {
      this.updateData()
      this.$on('selected', ori => {
        const nodes = findComponentsDownward(this, 'TreeNode')
        nodes.forEach(node => {
          this.$set(node.data, 'selected', false)
        })
        this.$set(ori, 'selected', true)
      })
      this.$on('checked', () => {
        this.updateData(false)
      })
      this.$on('on-selected', () => {
        this.$emit('on-select-change', this.getSelectedNodes())
      })
      this.$on('toggle-expand', (payload) => {
        this.$emit('on-toggle-expand', payload)
      })
    },
    methods: {
      getSelectedNodes () {
        const nodes = findComponentsDownward(this, 'TreeNode')
        return nodes.filter(node => node.data.selected).map(node => node.data)
      },
      updateData (isInit = true) {
        // init checked status
        function reverseChecked (data) {
          if (data.children) {
            let checkedLength = 0
            data.children.forEach(node => {
              if (node.children) node = reverseChecked(node)
              if (node.selected) checkedLength++
            })
            if (isInit) {
              if (checkedLength >= data.children.length) data.selected = true
            } else {
              data.selected = checkedLength >= data.children.length
            }
            return data
          } else {
            return data
          }
        }

        function forwardChecked (data) {
          if (data.children) {
            data.children.forEach(node => {
              if (data.selected) node.selected = true
              if (node.children) node = forwardChecked(node)
            })
            return data
          } else {
            return data
          }
        }
        this.data.map(node => reverseChecked(node)).map(node => forwardChecked(node))
        this.broadcast('TreeNode', 'indeterminate')
      }
    },
    watch: {
      data () {
        this.$nextTick(() => {
          this.updateData()
        })
      }
    }
  }
</script>
